<?php


	namespace app\services;


	use app\lib\exception\ToastException;

	class SnapPayServices
	{
		const URL = 'https://open.snappay.ca/api/gateway';
		//APPID
		private $app_id;

		//秘钥
		private $api_key;

		//商户号
		private $merchant_no;

		public function __construct () {
			$this->app_id = '2f8bf55e0c0ce452';
			$this->api_key = '85cee10ee5c82893e01880c7e09f76b7';
			$this->merchant_no = '902100037732';
		}

		public function barCodePay () {
			$params = [
				'app_id'         => $this->app_id,
				'format'         => 'JSON',
				'charset'        => 'UTF-8',
				'sign_type'      => 'MD5',
				'version'        => '1.0',
				'method'         => 'pay.barcodepay',
				'merchant_no'    => $this->merchant_no,
				'payment_method' => 'ALIPAY',
				'out_order_no'   => 'SH20210721135923' . random(6),
				'trans_amount'   => 1,
				'notify_url'     => 'https://notify-url',
				'auth_code'      => '28763443825664394',
				'description'    => '商品测试'
			];

			$post_data_sign = $this->snappay_sign_post_data($params, $this->api_key);
			$url = 'https://open.snappay.ca/api/gateway';
			$options = [
				'http' => [
					'method'  => 'POST',
					'header'  => "Content-Type: application/json\r\n" . "Accept: application/json\r\n",
					'content' => json_encode($post_data_sign)
				]
			];
			$context = stream_context_create($options);
			$result = json_decode(file_get_contents($url, false, $context), true);
			if ($result['code'] != '0') {
				throw new ToastException($result['msg'], $result['code']);
			}

			return $result;
		}

		public function inAppPay () {

			$params = [
				'app_id'               => $this->app_id,
				'method'               => 'pay.inapppay',
				'format'               => 'JSON',
				'charset'              => 'UTF-8',
				'sign_type'            => 'MD5',
				'version'              => '1.0',
				'merchant_no'          => $this->merchant_no,
				'payment_method'       => 'WECHATPAY',
				'out_order_no'         => 'SH20210721135923' . random(6),
				'trans_amount'         => 1,
				'notify_url'           => 'https://notify-url',
				'description'          => '商品测试',
				'effective_minutes'    => 20,
				'extension_parameters' => json_encode(['sub_app_id' => 'wxe0f599d48638e933'])
			];






			$post_data_sign = $this->snappay_sign_post_data($params, $this->api_key);

			print_r($post_data_sign);die;


			$url = 'https://open.snappay.ca/api/gateway';
			$options = [
				'http' => [
					'method'  => 'POST',
					'header'  => "Content-Type: application/json\r\n" . "Accept: application/json\r\n",
					'content' => json_encode($post_data_sign)
				]
			];
			$context = stream_context_create($options);
			$result = json_decode(file_get_contents($url, false, $context), true);
			if ($result['code'] != '0') {
				throw new ToastException($result['msg'], $result['code']);
			}

			return $result;
		}

		protected function snappay_sign_post_data ($post_data, $signKey) {
			$sign_type = $post_data['sign_type'];

			$para_filter = $this->snappay_paraFilter($post_data);

			$para_sort = $this->snappay_argSort($para_filter);

			$prestr = $this->snappay_createLinkstring($para_sort);

			$mysign = $this->snappay_md5Sign($prestr, $signKey);

			$para_sort['sign'] = $mysign;
			$para_sort['sign_type'] = $sign_type;

			return $para_sort;
		}

		public function snappay_sign_verify ($post_data, $signKey) {
			if (!isset($post_data) || !isset($post_data['sign'])) {
				return false;
			}

			$sign = $post_data['sign'];

			$para_filter = $this->snappay_paraFilter($post_data);

			$para_sort = $this->snappay_argSort($para_filter);

			$prestr = $this->snappay_createLinkstring($para_sort);

			$mysign = $this->snappay_md5Sign($prestr, $signKey);

			if ($sign === $mysign) {
				return true;
			} else {
				return false;
			}
		}

		protected function snappay_paraFilter ($para) {
			$para_filter = [];
			while (list ($key, $val) = $this->snappay_myEach($para)) {
				if ($key == "sign" || $key == "sign_type" || $val == "")
					continue; else    $para_filter[$key] = $para[$key];
			}

			return $para_filter;
		}

		protected function snappay_argSort ($para) {
			ksort($para);
			reset($para);

			return $para;
		}

		protected function snappay_createLinkstring ($para) {
			$arg = "";
			while (list ($key, $val) = $this->snappay_myEach($para)) {
				$arg .= $key . "=" . $val . "&";
			}
			$arg = substr($arg, 0, strlen($arg) - 1);

			if (get_magic_quotes_gpc()) {
				$arg = stripslashes($arg);
			}

			return $arg;
		}

		protected function snappay_md5Sign ($prestr, $key) {
			$prestr = $prestr . $key;

			return md5($prestr);
		}

		protected function snappay_myEach (&$arr) {
			$key = key($arr);
			$result = ($key === null) ? false : [$key, current($arr), 'key' => $key, 'value' => current($arr)];
			next($arr);

			return $result;
		}


		/**
		 * redis 缓存雪崩,缓存穿透,缓存击穿
		 *
		 *
		 * 穿透：key 对应的缓存数据 在缓存中和数据库中都不存在了
		 *      1.查询的数据要过滤,
		 *      2.查询的空结果也存到缓存系统中
		 *
		 * 击穿：key 对应的缓存数据,在缓冲不存在(一般过期或者真的不存在),数据库中存在
		 *
		 * 雪崩：缓存服务器重启或者大量的缓存数据同时失效
		 *
		 *
		 *
		 *
		 *
		 */



	}
